package com.stars.easyms.demo.rest.service.sentinel;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import com.stars.easyms.demo.rest.dto.input.sentinel.SentinelDemo6Input;
import com.stars.easyms.demo.rest.dto.output.sentinel.SentinelDemo6Output;
import com.stars.easyms.demo.util.DemoThreadUtil;
import com.stars.easyms.rest.RestService;
import com.stars.easyms.base.util.MessageFormatUtil;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;

@Service
public class SentinelDemo6Service implements RestService<SentinelDemo6Input, SentinelDemo6Output> {

    private static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(50);

    private static final String RESOURCE_NAME = SentinelDemo6Service.class.getSimpleName();

    @Override
    public SentinelDemo6Output execute(SentinelDemo6Input input) {
        defineSystemRule(input);
        AtomicInteger successCount = new AtomicInteger(0);
        AtomicInteger blockCount = new AtomicInteger(0);
        List<Future<Boolean>> futureList = new ArrayList<>();
        for (int i = 0; i < input.getTimes(); i++) {
            futureList.add(DemoThreadUtil.submit(EXECUTOR_SERVICE, () -> {
                try (Entry entry = SphU.entry(RESOURCE_NAME, EntryType.IN)) {
                    successCount.incrementAndGet();
                } catch (BlockException e1) {
                    blockCount.incrementAndGet();
                }
                return Boolean.TRUE;
            }));

        }
        DemoThreadUtil.getFutureResult(futureList);
        SentinelDemo6Output output = new SentinelDemo6Output();
        System.out.println(MessageFormatUtil.format("Rest Service[{}], param[{}]!", this.getClass().getSimpleName(), input));
        output.setSuccessCount(successCount.get());
        output.setBlockCount(blockCount.get());
        return null;
    }

    private void defineSystemRule(SentinelDemo6Input input) {
        SystemRule rule = new SystemRule();
        rule.setHighestSystemLoad(input.getHighestSystemLoad());
        rule.setHighestCpuUsage(input.getHighestCpuUsage());
        rule.setAvgRt(input.getAvgRt());
        rule.setQps(input.getQps());
        rule.setMaxThread(input.getMaxThread());
        SystemRuleManager.loadRules(Collections.singletonList(rule));
    }
}